package com.hj.springframework3.context;

import lombok.Data;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * @Author : hujing
 * @Date: 2025/7/4 16:29
 * @Description:
 */
@Data
public class BeanDefinition implements Comparable<BeanDefinition> {
    // bean的名称
    private final String name;
    // bean的声明类型,声明类型与实例的实际类型并不一致,比如声明类型是DataSource,实例类型可能是DruidDataSource
    private final Class<?> beanClass;
    // bean的实例(有可能是代理实例)
    private Object instance;
    // 构造方法
    private final Constructor<?> constructor;
    // 工厂方法名称
    private final String factoryName;
    // 工厂方法
    private final Method factoryMethod;
    // bean的顺序
    private final int order;
    // 是否表示@Primary
    private final boolean primary;
    // 初始化方法名称
    private String initMethodName;
    // 初始化方法
    private Method initMethod;
    // 销毁方法名称
    private String destroyMethodName;
    // 销毁方法
    private Method destroyMethod;

    // 定义通过构造方法创建BeanDefinition的构造器
    public BeanDefinition(String name, Class<?> beanClass, Constructor<?> constructor, int order, boolean primary, String initMethodName, String destroyMethodName, Method initMethod, Method destroyMethod) {
        this.name = name;
        this.beanClass = beanClass;
        this.constructor = constructor;
        this.factoryName = null;
        this.factoryMethod = null;
        this.order = order;
        this.primary = primary;
        // 设置构造方法为可访问
        constructor.setAccessible(true);
        setInitAndDestroyMethod(initMethodName, destroyMethodName, initMethod, destroyMethod);
    }

    // 定义通过工厂方法创建BeanDefinition的构造器
    public BeanDefinition(String name, Class<?> beanClass, String factoryName, Method factoryMethod, int order, boolean primary, String initMethodName, String destroyMethodName, Method initMethod, Method destroyMethod) {
        this.name = name;
        this.beanClass = beanClass;
        this.constructor = null;
        this.factoryName = factoryName;
        this.factoryMethod = factoryMethod;
        this.order = order;
        this.primary = primary;
        // 设置工厂方法为可访问
        factoryMethod.setAccessible(true);
        setInitAndDestroyMethod(initMethodName, destroyMethodName, initMethod, destroyMethod);
    }

    private void setInitAndDestroyMethod(String initMethodName, String destroyMethodName, Method initMethod, Method destroyMethod) {
        this.initMethodName = initMethodName;
        this.destroyMethodName = destroyMethodName;
        if (initMethod != null) {
            initMethod.setAccessible(true);
            this.initMethod = initMethod;
        }
        if (destroyMethod != null) {
            destroyMethod.setAccessible(true);
            this.destroyMethod = destroyMethod;
        }
    }

    @Override
    public int compareTo(BeanDefinition beanDefinition) {
        int cmp = Integer.compare(this.order, beanDefinition.order);
        if (cmp != 0) {
            return cmp;
        }
        return this.name.compareTo(beanDefinition.name);
    }
    
    public Object getRequiredInstance(){
        if (this.instance == null) {
            throw new RuntimeException("bean实例不存在");
        }
        return this.instance;
    }
}
